﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using Mpi.Common.Graphic;
using Xeml.Document;
using System.Diagnostics;
using Mpi.Common.Collections;
using System.Linq;

namespace Xeml.Visualization.Controls
{
    public enum DrawAreaStyle
    {
        GreenMetal,
        BlueMetal,
        SilverMetal

    }

    public partial class XemlViewer : ScrollableControl
    {
        private DrawAreaStyle _drawAreaStyle = DrawAreaStyle.GreenMetal;

        public DrawAreaStyle DrawAreaStyle
        {
            get { return _drawAreaStyle; }
            set
            {
                if (value != this._drawAreaStyle)
                {
                    _drawAreaStyle = value;
                    if (this.MtlsEnabled)
                        this.mtls.DrawAreaStyle = value;
                    Invalidate();
                }
            }
        }

        private int drawAreaOrigin; //stating poinmt drawarea

        private bool hasFocus;

        public bool HasFocus
        {
            get { return hasFocus; }
            set
            {
                if (value != hasFocus)
                {
                    hasFocus = value;
                    Invalidate();
                }

            }
        }


        private bool _heatMapOn = false;

        public bool HeatMapOn
        {
            get { return _heatMapOn; }
            set { _heatMapOn = value; }
        }

        private Term _selectedterm;
        public Term SelectedTerm
        {
            get
            {
                return _selectedterm;
            }
            set
            {
                if (_selectedterm != value)
                {
                    _selectedterm = value;
                    Invalidate();
                }
            }
        }


        private bool _showGrid;
        public bool ShowGrid
        {
            get { return _showGrid; }
            set { _showGrid = value; }
        }

        #region Constructors
        public XemlViewer()
        {
            //         ExtractBmps();
            InitializeComponent();
            toolStripMenuItemNewStory.Click += new EventHandler(toolStripMenuItemNewStory_Click);
            toolStripMenuItemObservationPoint.Click += new EventHandler(toolStripMenuItemObservationPoint_Click);
            toolStripMenuItemEvent.Click += new EventHandler(OnAddEvent);
            toolStripMenuItemSplit.Click += new EventHandler(toolStripMenuItemSplit_Click);
            toolStripMenuItemDelete.Click += new EventHandler(toolStripMenuItemDelete_Click);
            toolStripMenuItemSlectalll.Click += new EventHandler(toolStripMenuItemSlectalll_Click);

            toolStripButtonNewStory.Click += new EventHandler(toolStripMenuItemNewStory_Click);
            toolStripButtonSplit.Click += new EventHandler(toolStripMenuItemSplit_Click);
            toolStripButtonNewObservationPoint.Click += new EventHandler(toolStripMenuItemObservationPoint_Click);
            toolStripButtonAddEvent.Click += new EventHandler(OnAddEvent);
            toolStripMenuItemRefresh.Click += new EventHandler(toolStripMenuItemRefresh_Click);

            toolStripComboBoxZoom.SelectedIndex = 3;
            toolStripComboBoxZoom.SelectedIndexChanged += new EventHandler(toolStripComboBoxZoom_SelectedIndexChanged);
            toolStripButtonAlign.Click += new EventHandler(toolStripButtonAlign_Click);


            toolStripButtonHeatMap.Click += new EventHandler(toolStripButtonHeatMap_Click);
            toolStripButtonShowHideGrid.Click += new EventHandler(toolStripButtonShowHideGrid_Click);
            ToggleHeatMapButton();
            ToggleGridButton();

            InitDrawTools();


            this.SetStyle(ControlStyles.DoubleBuffer |
             ControlStyles.UserPaint |
             ControlStyles.AllPaintingInWmPaint,
             true);
            this.UpdateStyles();

            this.mtlsEnables = true;
            this.visualDoc = new VisualXemlDoc();

            //this.visualDoc.DocAreaOffSet = new Point(this.innerLeftMargin, this.innerTopMargin);

            this.visualDoc.Invalidated += new EventHandler(visualDoc_Invalidated);
            this.visualDoc.SelectedElementChanged += new EventHandler<SelectedElementChangedEventArgs>(visualDoc_SelectedElementChanged);
            this.visualDoc.HighLightedElementChanged += new EventHandler(OnHighLightedElementChanged);
            //this.visualDoc.LastTouchedChanged += new EventHandler<SelectedElementChangedEventArgs>(visualDoc_LastTouchedChanged);
            this.visualDoc.StoryAreaHeight = 60;

            //this.visualDoc.SelectedStoryChanged += new EventHandler(visualDoc_SelectedStoryChanged);
            //this.visualDoc.SelectedObservationPointChanged += new EventHandler(visualDoc_SelectedObservationPointChanged);
            //this.visualDoc.SelectedEventChanged += new EventHandler(visualDoc_SelectedEventChanged);
            //this.visualDoc.SelectedSwitchPointChanged += new EventHandler(visualDoc_SelectedSwitchPointChanged);

            //this.selectedObPoints = new List<Xeml.Document.ObservationPoint>();
            //this.selectedStoryBases = new List<Mpimp.Common.TreeNode<Xeml.Document.StoryBase>>();

            //this.storyAreas = new List<VisualStory>();
            //this.labels = new List<string>();
            //this.positions = new List<Point>();

            //trpm = new TimeRegionPixelMapper();
            //visualDoc.PxMapper.Regions = new TimeRegionList();
            //TimeRegion tr;

            //tr = new TimeRegion();
            //tr.Length = new TimeSpan(42,00,00,00);
            //tr.Resolution = 1f;
            //visualDoc.PxMapper.Regions.AddFirst(tr);

            //tr = new TimeRegion();
            //tr.Length = new TimeSpan(21, 00, 00, 00);
            //tr.Resolution = 1f;
            //visualDoc.PxMapper.Regions.AddLast(tr);



            //CalculateDrawAreaX();


            // tsl = new TimeSolutionSlider();
            //tsl.Width = 30;
            //tsl.Height = 15;
            //this.Controls.Add(tsl);
            //tsl.Left = 10;
            //tsl.Top = 20;
            //tsl.LocationChanged += new EventHandler(tsl_LocationChanged);

        }

        void toolStripButtonShowHideGrid_Click(object sender, EventArgs e)
        {
            ShowGrid = !ShowGrid;
            ToggleGridButton();
            Invalidate();
        }

        void toolStripButtonHeatMap_Click(object sender, EventArgs e)
        {
            HeatMapOn = !HeatMapOn;
            ToggleHeatMapButton();
            Invalidate();
        }

        private void ToggleHeatMapButton()
        {
            if (_heatMapOn)
            {
                toolStripButtonHeatMap.Image = BackgroundRes.Control_ColorDialog;
                toolStripButtonHeatMap.Text = "HeatMap Off";

            }
            else
            {
                toolStripButtonHeatMap.Image = BackgroundRes.Control_ColorDialog_Sepia;
                toolStripButtonHeatMap.Text = "HeatMap On";
            }
        }

        private void ToggleGridButton()
        {
            if (_showGrid)
            {
                toolStripButtonShowHideGrid.Image = BackgroundRes.ShowGridlines2HS;
                toolStripButtonShowHideGrid.Text = "Hide Grid";

            }
            else
            {
                toolStripButtonShowHideGrid.Image = BackgroundRes.ShowGridlines2HS_sepia;
                toolStripButtonShowHideGrid.Text = "Show Grid";
            }
        }

        void toolStripButtonAlign_Click(object sender, EventArgs e)
        {
            if (visualDoc.SelectedObPoint != null)
            {
                StoryBase sbSource = visualDoc.SelectedObPoint.ObservationPoint.Collection.Story;
                List<ObservationPoint> toAlign = new List<ObservationPoint>();
                foreach (VisObserverPoint vop in visualDoc.SelectedOpPoints)
                {
                    if (vop.ObservationPoint.Collection.Story != sbSource)
                    {
                        toAlign.Add(vop.ObservationPoint);
                    }
                }
                foreach (ObservationPoint op in toAlign)
                {
                    op.TimePoint = visualDoc.SelectedObPoint.ObservationPoint.TimePoint;
                }
            }
        }

        void toolStripComboBoxZoom_SelectedIndexChanged(object sender, EventArgs e)
        {
            decimal zoom = Convert.ToInt32(toolStripComboBoxZoom.Text);
            int newRes = (int)(PxMapper.StandarResolution / (zoom / 100));
            PxMapper.ApplyGlobalResolution(newRes);

        }




        void OnAddEvent(object sender, EventArgs e)
        {
            if (this.SelectedStoryBases.Length > 0)
            {
                //Debug.WriteLine("XemlViewer: Adding ObPoint at Mouse x = " + this.mouseX);
                //Debug.WriteLine("XemlViewer: Adding ObPoint at Mouse corrected x = " + (this.mouseX - innerLeftMargin));
                TimeSpan ts = this.PxMapper.MapPoint(this.mouseX - (innerLeftMargin + AutoScrollPosition.X));

                //Debug.WriteLine("XemlViewer: Adding ObPoint time = " + ts.ToString());
                Event ev = new Event();
                ev.TimePoint = ts;

                this.SelectedStoryBases[0].Content.Events.Add(ev);

            }
        }

        void toolStripMenuItemRefresh_Click(object sender, EventArgs e)
        {
            this.visualDoc.ResetDocument();
        }

        void toolStripMenuItemSlectalll_Click(object sender, EventArgs e)
        {
            foreach (VisObserverPoint vop in this.visualDoc.ObPoints)
            {
                vop.Selected = true;
            }
        }


        private void contextMenu_Opening(object sender, CancelEventArgs e)
        {
            Debug.WriteLine("XemlViewer:ContextMenueOpen");
            // EnableDisableContextMenue();

        }

        private void EnableDisableContextMenue()
        {
            if (this.SelectedObservationPoint == null)
                this.toolStripMenuItemObservationPoint.Enabled = false;
            else
                this.toolStripMenuItemObservationPoint.Enabled = true;
            if (this.SelectedStoryBase == null)
            {
                this.toolStripMenuItemObservationPoint.Enabled = false;
                this.toolStripMenuItemSplit.Enabled = false;
                this.toolStripMenuItemDelete.Enabled = false;
                this.toolStripMenuItemEvent.Enabled = false;
            }
            else
            {
                this.toolStripMenuItemObservationPoint.Enabled = true;
                this.toolStripMenuItemSplit.Enabled = true;
                this.toolStripMenuItemDelete.Enabled = true;
                this.toolStripMenuItemEvent.Enabled = true;
            }
        }

        void toolStripMenuItemDelete_Click(object sender, EventArgs e)
        {
            DeleteSelectedObject();

        }

        private void DeleteSelectedObject()
        {
            if (this.visualDoc.MostTopSelectedElement == VisualDocElement.Story || this.visualDoc.MostTopSelectedElement == VisualDocElement.SplitDot)
            {

                foreach (TreeNode<StoryBase> sbnode in this.SelectedStoryBases)
                {
                    this.xemlDoc.StoryBoard.Remove(sbnode);
                }
            }
            else if (this.visualDoc.MostTopSelectedElement == VisualDocElement.ObservationPoint)
            {

                foreach (ObservationPoint op in this.SelectedObservationPoints)
                {
                    DocumentHelper.ClearRelatedSampling(op);
                }
                foreach (ObservationPoint op in this.SelectedObservationPoints)
                {
                    //StoryBase sb = op.Collection.Owner as StoryBase;
                    op.Collection.Remove(op);// = null;
                    //this.SelectedStoryBase.Content.ObservationPoints.Remove(this.SelectedObservationPoint.ObjectIdentifiere);
                }
                if (this.mtls != null)
                {
                    this.mtls.DeactivateTimeEditor(true);
                }
            }
            else if (this.visualDoc.MostTopSelectedElement == VisualDocElement.Event)
            {
                if (this.mtls != null)
                {
                    this.mtls.DeactivateTimeEditor(true);
                }
                this.SelectedStoryBase.Content.Events.Remove(this.SelectedEvent);
            }
        }

        void toolStripMenuItemSplit_Click(object sender, EventArgs e)
        {
            Split();
        }

        private void Split()
        {
            if (this.SelectedStoryBases.Length > 0)
            {
                StorySplit ss = new StorySplit();
                TimeSpan ts = this.PxMapper.MapPoint(this.mouseX - (innerLeftMargin + AutoScrollPosition.X));
                ss.TimePoint = ts;

                this.xemlDoc.StoryBoard.Add(this.SelectedStoryBases[0], ss);
            }
        }

        void toolStripMenuItemObservationPoint_Click(object sender, EventArgs e)
        {
            SetObservation();
        }

        private void SetObservation()
        {
            if (this.SelectedStoryBases.Length > 0)
            {
                //Debug.WriteLine("XemlViewer: Adding ObPoint at Mouse x = " + this.mouseX);
                //Debug.WriteLine("XemlViewer: Adding ObPoint at Mouse corrected x = " + (this.mouseX - innerLeftMargin));
                TimeSpan ts = this.PxMapper.MapPoint(this.mouseX - (innerLeftMargin + AutoScrollPosition.X));
                if (!this.SelectedStoryBases[0].Content.ObservationPoints.Contains(ts))
                {
                    //Debug.WriteLine("XemlViewer: Adding ObPoint time = " + ts.ToString());
                    ObservationPoint op = new ObservationPoint();
                    op.TimePoint = ts;
                    op.Id = DocumentHelper.NextObservationId(this.xemlDoc.StoryBoard);
                    this.SelectedStoryBases[0].Content.ObservationPoints.Add(op);
                }
            }
        }

        void toolStripMenuItemNewStory_Click(object sender, EventArgs e)
        {

            NewStory();
        }

        private void NewStory()
        {
            if (this.xemlDoc != null)
            {
                this.xemlDoc.StoryBoard.Add(new Story());
            }


        }





        #endregion

        #region Brushes, Pens, Colors, Fonts
        const string disabledText = "DESIGNER DISABLED";

        private Image bckg;
        private Image logo;
        Font xpTitleFont;
        Font storyLabelFont;
        Font logoFont;
        Font disabledFont;
        Size disableTextSize;

        Pen edgesPen;
        Pen opPointPen;
        Pen opPointPreviewPen;
        Pen relationPen;
        Pen hourGridPen;
        Pen dayGridPen;
        Pen weekGridPen;
        Pen focusPen;
        Pen editModePen;
        Pen eventPen;

        Brush opPointBrush;
        Brush opPointPreviewBrush;
        Brush edgesBrush;
        Brush drawAreaBrush;
        Brush eventBrush;

        GraphicsPath arrow;
        CustomLineCap arrowCap;
        Brush disabledBrush;


        private void InitDrawTools()
        {
            //  this.bckg = (Image)BackgroundRes.BackGreen;
            this.logo = (Image)BackgroundRes.XemlLogo5;

            xpTitleFont = new Font("Verdana", 12f, FontStyle.Bold);
            storyLabelFont = new Font("Verdana", 10f, FontStyle.Regular);
            logoFont = new Font("Verdana", 6f, FontStyle.Regular);

            dayGridPen = new Pen(Color.FromArgb(160, Color.Black));
            weekGridPen = new Pen(Color.FromArgb(160, Color.Black), 2f);
            hourGridPen = new Pen(Color.FromArgb(160, Color.Black), 1f);

            hourGridPen.DashStyle = DashStyle.Dash;
            hourGridPen.DashPattern = new float[] { 5f, 5f };

            edgesBrush = new SolidBrush(Color.RoyalBlue);
            edgesPen = new Pen(edgesBrush, 2f);
            opPointPen = new Pen(Color.FromArgb(255, 66, 101, 62));
            opPointBrush = new SolidBrush(Color.FromArgb(255, 116, 176, 109));
            opPointPreviewPen = new Pen(Color.FromArgb(180, 66, 101, 62));
            opPointPreviewBrush = new SolidBrush(Color.FromArgb(120, 116, 176, 109));
            eventBrush = new SolidBrush(Color.FromArgb(221, 219, 82));
            eventPen = new Pen(Color.Black);


            relationPen = new Pen(Brushes.DarkRed, 2f);
            arrow = new GraphicsPath();
            arrow.AddLine(0, 0, -2, -2);
            arrow.AddLine(0, 0, 2, -2);
            arrowCap = new CustomLineCap(null, arrow);
            relationPen.CustomEndCap = arrowCap;

            drawAreaBrush = new SolidBrush(Color.FromArgb(160, Color.White));
            disabledBrush = new SolidBrush(Color.FromArgb(180, Color.Black));
            disabledFont = new Font("Verdana", 28f);
            disableTextSize = TextRenderer.MeasureText(disabledText, disabledFont);

            focusPen = new Pen(Color.FromArgb(100, Color.Blue), 4f);
            editModePen = new Pen(Color.FromArgb(100, Color.Yellow), 4f);

        }

        #endregion

        protected override void OnPaint(PaintEventArgs pe)
        {
            //CalculateDrawAreaX();
            //Init some useful variables
            Graphics g = pe.Graphics;
            int width = (int)Math.Max(this.Width, this.AutoScrollMinSize.Width);
            int height = (int)Math.Max(this.Height, this.AutoScrollMinSize.Height);
            Rectangle controlRect = new Rectangle(0, 0, width - 1, height - 1);

            //set quality           
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;





            //compensate scrolling
            g.TranslateTransform(AutoScrollPosition.X, AutoScrollPosition.Y);

            //background kacheln
            PaintBackground(g, width, height);


            if (this.Focused)
            {

                if (keyEditMode)
                {
                    g.DrawRectangle(editModePen, controlRect);
                }
                else
                {
                    g.DrawRectangle(focusPen, controlRect);
                }
            }

            //xeml logo
            PaintLogo(g, width, height);

            //draw margins
            //PaintMargins(g, width, height);



            g.TranslateTransform(innerLeftMargin, this.innerTopMargin); //translate all to the drawarea origin


            if (_showGrid)
                DrawTimeGrid(g);
            //Paint the content
            if (this.xemlDoc != null)
            {

                PaintDocContent(g);
            }


            if (dragTimeEditing || keyEditMode)
            {

            }


            if (timeEditPreviewMode)
            {
                Debug.WriteLine("XemlViewer: Paint Preview Mode is On");
                // DrawTimeGrid(g);
                //g.DrawLine(Pens.Blue, 300, -50, 300, 3000);

                //if (activeHotSpot > 0)
                //{
                //    g.DrawLine(Pens.Red, activeHotSpot, -20, activeHotSpot, height);
                //}

                g.TranslateTransform(timeEditPreviewXOffSet, 0);



                if (this.visualDoc.MostTopSelectedElement == VisualDocElement.ObservationPoint)
                {
                    Debug.WriteLine("XemlViewer: Paint ObPoint Preview");
                    g.FillPath(opPointPreviewBrush, visualDoc.SelectedObPoint.Shape);
                    g.DrawPath(opPointPreviewPen, visualDoc.SelectedObPoint.Shape);
                }
                else if (this.visualDoc.MostTopSelectedElement == VisualDocElement.SplitDot || this.visualDoc.MostTopSelectedElement == VisualDocElement.Story)
                {
                    Debug.WriteLine("XemlViewer: Paint SplitDot Preview");
                    //g.FillPath(opPointPreviewBrush, visualDoc.SelectedObPoint.Shape);
                    g.DrawPath(Pens.Gray, visualDoc.SelectedSplitDot.Shape);
                }
                else if (this.visualDoc.MostTopSelectedElement == VisualDocElement.Event)
                {
                    Debug.WriteLine("XemlViewer: Paint Event Preview");
                    //g.FillPath(opPointPreviewBrush, visualDoc.SelectedObPoint.Shape);
                    g.DrawPath(Pens.Gray, visualDoc.SelectedEvent.Shape);
                }
                g.TranslateTransform(-timeEditPreviewXOffSet, 0);
            }




            //´Paint disabled state
            if (!this.Enabled)
            {
                g.TranslateTransform(-innerLeftMargin - 1, -this.innerTopMargin - 1);
                PaintDisabledMessage(g, width, height);
            }


            base.OnPaint(pe);
        }

        private void PaintDisabledMessage(Graphics g, int width, int height)
        {
            g.FillRectangle(disabledBrush, 0, 0, width, height);
            RectangleF rect = new RectangleF((width / 2) - (disableTextSize.Width / 2), (height / 2) - (disableTextSize.Height / 2), disableTextSize.Width, disableTextSize.Height);

            GraphicEffect.DrawSmoothBackGround(g, rect, Color.White, 50, 20, 40, 70);
            TextRenderer.DrawText(g, disabledText, disabledFont, Rectangle.Round(rect), Color.Maroon);
        }

        private void PaintDocContent(Graphics g)
        {
            //draw experiment title
            TextRenderer.DrawText(g, this.xemlDoc.Name, xpTitleFont, new Point(this.innerLeftMargin + AutoScrollPosition.X + 5, 40 + AutoScrollPosition.Y), Color.Black);


            if (!_heatMapOn || SelectedTerm == null || !(SelectedTerm is DynamicTerm))
                g.DrawPath(edgesPen, this.visualDoc.Edges);
            else if (SelectedTerm != null && SelectedTerm is DynamicTerm)
            {
                double min = double.MaxValue;
                double max = double.MinValue;
                string context = "";
                bool contextHasQuantitativeValuesOnly = false;

                DynamicTerm term = SelectedTerm as DynamicTerm;
                var contexts = term.Values.Where(x => x.Context != "ResponseRange").Select(x => x.Context).Distinct().ToList();
                foreach (var c in contexts)
                {
                    contextHasQuantitativeValuesOnly = true;
                    foreach (var storyline in visualDoc.StoryLines)
                    {
                        context = c;
                        var vals = storyline.Key.HistoryValues(term.TermId, c);
                        bool storyHasQunatitativeValuesOnly = vals.Count > 0;
                        foreach (var val in vals)
                        {
                            if (val.Value is Cycle)
                            {
                                foreach (var item in (val.Value as Cycle).Values)
                                {
                                    if (!Double.IsNaN((item as DynamicValue).DoubleValue))
                                    {
                                        min = Math.Min((item as DynamicValue).DoubleValue, min);
                                        max = Math.Max((item as DynamicValue).DoubleValue, max);
                                    }
                                    else
                                    {
                                        storyHasQunatitativeValuesOnly = false;
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                if (!Double.IsNaN((val.Value as DynamicValue).DoubleValue))
                                {
                                    min = Math.Min((val.Value as DynamicValue).DoubleValue, min);
                                    max = Math.Max((val.Value as DynamicValue).DoubleValue, max);
                                }
                                else
                                {
                                    storyHasQunatitativeValuesOnly = false;
                                    break;
                                }
                            }
                        }
                        contextHasQuantitativeValuesOnly = contextHasQuantitativeValuesOnly && storyHasQunatitativeValuesOnly;
                        if (!storyHasQunatitativeValuesOnly)
                            break;
                    }
                    if (contextHasQuantitativeValuesOnly)
                    {
                        break; //ok we found a context with quantitive values only
                    }
                }

                if (!contextHasQuantitativeValuesOnly)
                {
                    //nothing found to heatmap, lets fall back 
                    g.DrawPath(edgesPen, this.visualDoc.Edges);
                }
                else
                {
                    //lets draw a heatmap
                    foreach (var storyline in visualDoc.StoryLines)
                    {


                        var vals = storyline.Key.HistoryValues(term.TermId, context);
                        foreach (var vb in vals.Values)
                        {

                            RectangleF rf = storyline.Value.GetBounds();
                            Rectangle r = Rectangle.Round(rf);

                            Brush br = HeatMapper.ValueToBrush(this.PxMapper, vb, min, max, Color.Blue, Color.Red);
                            Pen p = new Pen(br, 11f);
                            if (storyline.Key is Story)
                            {
                                float left = (float)PxMapper.MapPoint(vb.Time);
                                g.DrawLine(p, left, r.Top, r.Right, r.Top);
                            }
                            else
                            {

                                g.DrawPath(Pens.Black, storyline.Value);
                                float left = Math.Max((float)PxMapper.MapPoint(vb.Time), r.Left);

                                g.DrawLine(p, left, r.Bottom, r.Right, r.Bottom);
                            }

                            br.Dispose();
                            p.Dispose();
                        }
                    }

                }

            }

            //draw nodes
            if (!_heatMapOn)
            {
                foreach (VisSplitDot sd in this.visualDoc.SplitDots)
                {
                    if (sd.IsHighLighted)
                    {
                        g.FillPath(Brushes.OrangeRed, sd.Shape);
                        g.DrawPath(edgesPen, sd.Shape);
                    }
                    else if (sd.Selected)
                    {
                        g.FillPath(Brushes.Yellow, sd.Shape);
                        g.DrawPath(edgesPen, sd.Shape);
                    }
                    else
                    {
                        g.FillPath(Brushes.Orange, sd.Shape);
                        g.DrawPath(edgesPen, sd.Shape);
                    }
                }

                //draw switches


                foreach (VisSwitchDot sd in this.visualDoc.SwitchDots)
                {
                    if (sd.IsHighLighted)
                    {
                        g.FillPath(Brushes.OrangeRed, sd.Shape);
                    }
                    else
                    {
                        g.FillPath(edgesBrush, sd.Shape);
                    }
                }
            }
            //draw observer points

            foreach (VisObserverPoint vop in this.visualDoc.ObPoints)
            {
                if (vop.IsHighLighted)
                {
                    g.DrawPath(opPointPen, vop.Shape);
                    GraphicEffect.DrawHighLightedBackground(g, vop.Shape, Color.OrangeRed, Color.Transparent);
                }
                else if (vop.Selected)
                {
                    g.DrawPath(opPointPen, vop.Shape);
                    GraphicEffect.DrawHighLightedBackground(g, vop.Shape, Color.Red, Color.Transparent);
                }
                else
                {
                    g.FillPath(opPointBrush, vop.Shape);
                    g.DrawPath(opPointPen, vop.Shape);
                }
            }

            foreach (VisEvent ve in this.visualDoc.VisEvents)
            {
                if (ve.IsHighLighted)
                {
                    g.FillPath(Brushes.Yellow, ve.Shape);
                    g.DrawPath(eventPen, ve.Shape);
                    // GraphicEffect.DrawHighLightedBackground(g, ve.Shape, Color.OrangeRed, Color.Transparent);
                }
                else if (ve.Selected)
                {
                    g.DrawPath(eventPen, ve.Shape);
                    GraphicEffect.DrawHighLightedBackground(g, ve.Shape, Color.Red, Color.Transparent);
                }
                else
                {
                    g.FillPath(eventBrush, ve.Shape);
                    g.DrawPath(eventPen, ve.Shape);
                }
            }

            //if (obPointHighLighted)
            //{
            //    GraphicEffect.DrawHighLightedBackground(g, visualDoc.HighLightedObPoint.HighLightSurround, Color.Red, Color.Transparent);
            //}

            //draw observer relations
            //foreach (GraphicsPath gp in this.visualDoc.OpRealtionPaths)
            //{
            //    g.DrawPath(relationPen, gp);
            //}

            foreach (VisStory vs in this.visualDoc.VisualStories)
            {
                RectangleF vsa = vs.BoundsF;
                vsa.Height -= 3f;
                if (vs.IsHighLighted && !vs.Selected)
                {
                    RectangleF glowRect = new RectangleF(vsa.X, vsa.Bottom - 20, vsa.Width, 20);
                    GraphicEffect.DrawGlassRectangle(g, vsa, Color.White, 20, 0.22f, true);
                    GraphicEffect.DrawEllipticGlow(g, glowRect, Color.FromArgb(200, Color.White), Color.FromArgb(180, Color.White), 0.1f);
                }
                else if (vs.IsHighLighted && vs.Selected)
                {
                    RectangleF glowRect = new RectangleF(vsa.X, vsa.Bottom - 20, vsa.Width, 20);
                    GraphicEffect.DrawGlassRectangle(g, vsa, Color.Orange, 20, 0.22f, true);
                    GraphicEffect.DrawEllipticGlow(g, glowRect, Color.FromArgb(200, Color.Orange), Color.FromArgb(180, Color.OrangeRed), 0.3f);
                }
                else if (vs.Selected)
                {
                    GraphicEffect.DrawGlassRectangle(g, vsa, Color.Orange, 20, 0.22f, true);
                }
                else
                    GraphicEffect.DrawGlassRectangle(g, vsa, Color.Black, 35, 0.22f, true);


                TextRenderer.DrawText(g, vs.Story.Content.Label, storyLabelFont, new Point(vs.Bounds.Left + this.innerLeftMargin + AutoScrollPosition.X + 5, (vs.Bounds.Bottom - 23) + innerTopMargin + AutoScrollPosition.Y), Color.FromArgb(20, 20, 20));
            }
        }

        private void PaintMargins(Graphics g, int width, int height)
        {
            g.DrawLine(Pens.Black, innerLeftMargin, 0, innerLeftMargin, height);
            g.DrawLine(Pens.Black, width - innerRightMargin, 0, width - innerRightMargin, height);
            g.DrawLine(Pens.Black, 0, innerTopMargin, width, innerTopMargin);
            g.DrawLine(Pens.Black, 0, this.Height - innerBottomMargin, width, this.Height - innerBottomMargin);
        }

        private void PaintLogo(Graphics g, int width, int height)
        {
            g.DrawImage(logo, width - 40 - 3, height - 32 - 3, 40, 32);
            TextRenderer.DrawText(g, "powered", logoFont, new Point(width + AutoScrollPosition.X - 42, height + AutoScrollPosition.Y - 10), Color.Black);
        }

        private void PaintBackground(Graphics g, int width, int height)
        {
            Image bck = null;
            switch (DrawAreaStyle)
            {
                case DrawAreaStyle.GreenMetal:
                    {
                        bck = BackgroundRes.GreenMetal_MaxPlanck;
                        break;
                    }
                case DrawAreaStyle.BlueMetal:
                    {
                        bck = BackgroundRes.BlueMetal_MaxPlanck;
                        break;
                    }
                case DrawAreaStyle.SilverMetal:
                    {
                        bck = BackgroundRes.SilverMetal_MaxPlanck;
                        break;
                    }
                default:
                    {
                        bck = BackgroundRes.GreenMetal_MaxPlanck;
                        break;
                    }
            }

            int horiCount = 1;
            int vertCount = 1;
            //int w = 300;
            //int h = 500;

            if (this.xemlDoc != null)
            {
                //w = 1024;
                //h = 768;
                horiCount = (width / bck.Width) + 1;
                vertCount = ((height - mtls.Bottom) / bck.Height) + 1;
            }


            for (int i = 0; i < horiCount; i++)
            {
                for (int j = 0; j < vertCount; j++)
                {
                    g.DrawImage(bck, (i * bck.Width), (j * bck.Height) + mtls.Bottom);
                }
            }
        }

        private void DrawTimeGrid(Graphics g)
        {
            foreach (int i in PxMapper.WeekSteps)
            {

                g.DrawLine(weekGridPen, i, 0, i, this.Height - innerBottomMargin - innerTopMargin);


            }
            foreach (int i in PxMapper.DaySteps)
            {
                g.DrawLine(dayGridPen, i, 0, i, this.Height - innerBottomMargin - innerTopMargin);

            }
            foreach (int i in PxMapper.HourSteps)
            {
                g.DrawLine(hourGridPen, i, 0, i, this.Height - innerBottomMargin - innerTopMargin);

            }
        }

        private int[] MajorTimeGrid()
        {
            if (visualDoc.PxMapper.WeekSteps.Length > 0)
                return visualDoc.PxMapper.WeekSteps;
            if (visualDoc.PxMapper.DaySteps.Length > 0)
                return visualDoc.PxMapper.DaySteps;
            if (visualDoc.PxMapper.HourSteps.Length > 0)
                return visualDoc.PxMapper.HourSteps;
            if (visualDoc.PxMapper.MinuteSteps.Length > 0)
                return visualDoc.PxMapper.MinuteSteps;

            return new int[0] { };
        }

        private int[] MinorTimeGrid()
        {
            if (visualDoc.PxMapper.WeekSteps.Length > 0)
                return visualDoc.PxMapper.DaySteps;
            if (visualDoc.PxMapper.DaySteps.Length > 0)
                return visualDoc.PxMapper.HourSteps;
            if (visualDoc.PxMapper.HourSteps.Length > 0)
                return visualDoc.PxMapper.MinuteSteps;

            return new int[0] { };
        }


        #region Event-/handling


        private bool dragTimeEditing = false;
        private bool DragTimeEditing
        {
            get
            {
                return dragTimeEditing;
            }
            set
            {
                if (dragTimeEditing != value)
                {
                    this.dragTimeEditing = value;
                    Debug.WriteLine(String.Format("XemlViewer: dragtime={0}", value));
                    Invalidate();
                }
            }
        }



        private int mouseX = 0;
        private int mouseY = 0;
        private int activeHotSpot = -1;
        protected override void OnMouseMove(MouseEventArgs e)
        {
            this.mouseX = e.X;
            this.mouseY = e.Y;
            // Debug.WriteLine("XemlViewer: Mouse x = " + this.mouseX);


            if (keyEditMode)
            {
                visualDoc.TrySelect(e.X - (innerLeftMargin + this.AutoScrollPosition.X), e.Y - (innerTopMargin + this.AutoScrollPosition.Y), strgPressed);
            }

            if (dragTimeEditing && MtlsEnabled)
            {
                mtls.MoveTimeEditor(e.X - (innerLeftMargin + this.AutoScrollPosition.X));
                //if (visualDoc.HotSpots.Contains(e.X - (innerLeftMargin + this.AutoScrollPosition.X)))
                //    activeHotSpot = e.X - (innerLeftMargin + this.AutoScrollPosition.X);
                //else
                //    activeHotSpot = -1;
            }
            visualDoc.TryHighLight(e.X - (innerLeftMargin + this.AutoScrollPosition.X), e.Y - (innerTopMargin + this.AutoScrollPosition.Y));
            base.OnMouseMove(e);
        }


        protected override void OnMouseDown(MouseEventArgs e)
        {
            this.Focus();
            if (e.Button == MouseButtons.Left)
            {
                //Debug.WriteLine("XemlViewer: Try to select ........................");
                //visualDoc.TrySelect(e.X - (innerLeftMargin + this.AutoScrollPosition.X), e.Y - (innerTopMargin + this.AutoScrollPosition.Y));
                Debug.WriteLine("XemlViewer: Try to select ........................");
                visualDoc.TrySelect(e.X - (innerLeftMargin + this.AutoScrollPosition.X), e.Y - (innerTopMargin + this.AutoScrollPosition.Y), strgPressed);


                if (visualDoc.IsOverTimeEditableObject(e.X - (innerLeftMargin + this.AutoScrollPosition.X), e.Y - (innerTopMargin + this.AutoScrollPosition.Y)) && MtlsEnabled)
                {

                    DragTimeEditing = true;
                }
            }
            base.OnMouseDown(e);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && this.timeEditPreviewMode && DragTimeEditing)
            {
                mtls.AcceptTimeEdit();

            }
            else if (e.Button == MouseButtons.Left || e.Button == MouseButtons.Right)
            {
                //Debug.WriteLine("XemlViewer: Try to select ........................");
                //visualDoc.TrySelect(e.X - (innerLeftMargin + this.AutoScrollPosition.X), e.Y - (innerTopMargin + this.AutoScrollPosition.Y), strgPressed);
                EnableDisableContextMenue();
            }
            DragTimeEditing = false;
            base.OnMouseUp(e);
        }

        protected override void OnMouseClick(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Middle)
                KeyEditMode = !KeyEditMode;
            base.OnMouseClick(e);

            if (ObservationPointSelected != null)
            {
                ObservationPointSelected(this, new Document.XemlEventArgs.ObservationPointSelectedEventArgs(this.SelectedObservationPoint));
            }

            Invalidate();
        }

        public event EventHandler<Xeml.Document.XemlEventArgs.ObservationPointSelectedEventArgs> ObservationPointSelected;

        protected override void OnMouseLeave(EventArgs e)
        {
            if (MtlsEnabled && dragTimeEditing)
                mtls.AcceptTimeEdit();
            dragTimeEditing = false;
            visualDoc.TryHighLight(-10, -10);
            base.OnMouseLeave(e);
        }

        protected override void OnMouseWheel(MouseEventArgs e)
        {
            TimeSpan timeScrollOffset = TimeSpan.Zero;
            switch (this.timeScoll)
            {
                case TimeScrollMode.Week:
                    {
                        timeScrollOffset = TimeSpan.FromDays(7);
                        break;
                    }
                case TimeScrollMode.Day:
                    {
                        timeScrollOffset = TimeSpan.FromDays(1);
                        break;
                    }
                case TimeScrollMode.Hour:
                    {
                        timeScrollOffset = TimeSpan.FromHours(1);
                        break;
                    }
                case TimeScrollMode.Minute:
                    {
                        timeScrollOffset = TimeSpan.FromMinutes(1);
                        break;
                    }
                case TimeScrollMode.Second:
                    {
                        timeScrollOffset = TimeSpan.FromSeconds(1);
                        break;
                    }
                default:
                    {
                        timeScrollOffset = TimeSpan.FromMinutes(PxMapper.StandarResolution);
                        break;
                    }
            }


            if (visualDoc.MostTopSelectedElement == VisualDocElement.ObservationPoint && this.SelectedObservationPoint != null)
            {

                if (e.Delta > 0)
                {
                    foreach (VisObserverPoint vop in visualDoc.SelectedOpPoints)
                    {
                        vop.ObservationPoint.TimePoint += timeScrollOffset;
                    }
                }
                else if (e.Delta < 0)
                {
                    foreach (VisObserverPoint vop in visualDoc.SelectedOpPoints)
                    {
                        vop.ObservationPoint.TimePoint -= timeScrollOffset;
                    }
                }
            }
            else if ((visualDoc.MostTopSelectedElement == VisualDocElement.Story || visualDoc.MostTopSelectedElement == VisualDocElement.SplitDot) && this.SelectedStoryBase != null && this.SelectedStoryBase.Content is StorySplit)
            {
                StorySplit ss = this.SelectedStoryBase.Content as StorySplit;
                if (e.Delta > 0)
                    ss.TimePoint += timeScrollOffset;
                else if (e.Delta < 0)
                {
                    ss.TimePoint -= timeScrollOffset;
                }
            }
            else if (visualDoc.MostTopSelectedElement == VisualDocElement.Event && this.SelectedEvent != null)
            {

                if (e.Delta > 0)
                    foreach (VisEvent ve in visualDoc.SelectedEvents)
                    {
                        ve.Event.TimePoint += timeScrollOffset;
                    }

                else if (e.Delta < 0)
                {
                    foreach (VisEvent ve in visualDoc.SelectedEvents)
                    {
                        ve.Event.TimePoint -= timeScrollOffset;
                    }
                }
            }
            else
                base.OnMouseWheel(e);
        }



        private bool keyEditMode;

        private bool KeyEditMode
        {
            get { return keyEditMode; }
            set
            {
                if (keyEditMode != value)
                {
                    keyEditMode = value;
                    if (keyEditMode)
                        this.Cursor = Cursors.Cross;
                    else
                        this.Cursor = Cursors.Default;
                    Invalidate();
                }
            }
        }

        // bool doTimeScroll = false;


        private TimeScrollMode timeScoll = TimeScrollMode.Default;
        protected override void OnKeyDown(KeyEventArgs e)
        {

            switch (e.KeyCode)
            {

                case Keys.ControlKey:
                    {
                        strgPressed = true;
                        //Debug.WriteLine("XemlViewer KeyDown: " + e.KeyCode);
                        Debug.WriteLine("XemlViewer: Ctrl press..");
                        break;
                    }
                case Keys.H:
                    {
                        this.timeScoll = TimeScrollMode.Hour;
                        break;
                    }
                case Keys.D:
                    {
                        this.timeScoll = TimeScrollMode.Day;
                        break;
                    }
                case Keys.M:
                    {
                        this.timeScoll = TimeScrollMode.Minute;
                        break;
                    }
                case Keys.S:
                    {
                        this.timeScoll = TimeScrollMode.Second;
                        break;
                    }
                case Keys.W:
                    {
                        this.timeScoll = TimeScrollMode.Week;
                        break;
                    }
                default:
                    break;
            }

            //if (e.KeyCode == Keys.ControlKey)
            //{
            //    strgPressed = true; 
            //    //Debug.WriteLine("XemlViewer KeyDown: " + e.KeyCode);
            //    Debug.WriteLine("XemlViewer: Ctrl press..");
            //}
            base.OnKeyDown(e);
        }


        private bool strgPressed = false;
        protected override void OnKeyUp(KeyEventArgs e)
        {
            this.timeScoll = TimeScrollMode.Default;
            Debug.WriteLine("XemlViewer Keyup: " + e.KeyCode);
            if (e.KeyCode == Keys.ControlKey)
            {
                strgPressed = false;
                Debug.WriteLine("XemlViewer: Ctrl release..");
            }

            base.OnKeyUp(e);
        }

        protected override bool IsInputKey(Keys keyData)
        {
            //Debug.WriteLine(keyData.ToString());
            //if (keyData == (Keys.LButton | Keys.ShiftKey | Keys.Control))
            // return true;
            return base.IsInputKey(keyData);
        }




        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            e.Handled = true;
            Debug.WriteLine("XemlViewer: Keychar = " + e.KeyChar);




            if (e.KeyChar == 'e')
                KeyEditMode = !KeyEditMode;

            if (e.KeyChar == 'n' && KeyEditMode)
            {
                NewStory();
            }
            if (e.KeyChar == 'o' && KeyEditMode)
            {
                SetObservation();
            }
            if (e.KeyChar == 's' && KeyEditMode)
            {
                Split();
            }
            if (e.KeyChar == 'd' && KeyEditMode)
            {
                DeleteSelectedObject();
            }



            base.OnKeyPress(e);
        }



        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            //SetupPositions();
            Invalidate(false);
        }

        protected override void OnEnabledChanged(EventArgs e)
        {

            base.OnEnabledChanged(e);
        }

        protected override void OnGotFocus(EventArgs e)
        {
            HasFocus = true;
            base.OnGotFocus(e);
        }

        protected override void OnLostFocus(EventArgs e)
        {
            HasFocus = false;
            base.OnLostFocus(e);
        }

        void visualDoc_Invalidated(object sender, EventArgs e)
        {
            this.AdjustSize();
            //this.SetupPositions();
            Invalidate(false);
        }




        void visualDoc_SelectedElementChanged(object sender, SelectedElementChangedEventArgs e)
        {

            if (this.mtls != null)
            {
                mtls.DeactivateTimeEditor(true);
                mtls.Enabled = true;
            }

            object x = visualDoc.SelectedOpPoints;
            if (e.MostTopSelectedElement == VisualDocElement.ObservationPoint)
            {
                if (this.mtls != null)
                {
                    if (visualDoc.SelectedObPoint != null)
                    {
                        if (this.SelectedStoryBase != null && this.SelectedObservationPoints.Length > 0)
                        {
                            TimeSpan editTime = visualDoc.SelectedObPoint.ObservationPoint.TimePoint;
                            TimeSpan min = TimeSpan.Zero;
                            TimeSpan max = xemlDoc.StoryBoard.ObservationTime;
                            if (this.SelectedStoryBase.Content is StorySplit)
                                min = (this.SelectedStoryBase.Content as StorySplit).TimePoint;
                            max -= TimeSpan.FromSeconds(1);
                            mtls.ActivateTimeEditor(editTime, min, max, visualDoc.SelectedObPoint.ObservationPoint);
                        }
                        else
                            mtls.Enabled = false;
                    }
                }
            }
            else if (e.MostTopSelectedElement == VisualDocElement.SplitDot || e.MostTopSelectedElement == VisualDocElement.Story)
            {
                if (this.MtlsEnabled && this.SelectedStoryBase.Content is StorySplit)
                {
                    if (visualDoc.SelectedStory != null && visualDoc.SelectedStory.Story.Content is StorySplit)
                    {
                        TimeSpan min = TimeSpan.Zero;
                        TimeSpan max = xemlDoc.StoryBoard.ObservationTime;
                        if (this.SelectedStoryBase.Parent != null)
                        {
                            if (this.SelectedStoryBase.Parent.Content is StorySplit)
                                min = (this.SelectedStoryBase.Parent.Content as StorySplit).TimePoint;
                        }
                        min += TimeSpan.FromSeconds(1);
                        max -= TimeSpan.FromSeconds(1);

                        TimeSpan editTime = visualDoc.SelectedStory.Time;
                        mtls.ActivateTimeEditor(editTime, min, max, visualDoc.SelectedStory.Story.Content as StorySplit);
                    }
                }
            }
            else if (e.MostTopSelectedElement == VisualDocElement.Event)
            {
                if (this.MtlsEnabled)
                {
                    if (visualDoc.SelectedEvent != null)
                    {
                        if (this.SelectedStoryBase != null && visualDoc.SelectedEvent != null)
                        {
                            TimeSpan editTime = visualDoc.SelectedEvent.Event.TimePoint;
                            TimeSpan min = TimeSpan.Zero;
                            TimeSpan max = xemlDoc.StoryBoard.ObservationTime;
                            if (this.SelectedStoryBase.Content is StorySplit)
                                min = (this.SelectedStoryBase.Content as StorySplit).TimePoint;
                            max -= TimeSpan.FromSeconds(1);
                            mtls.ActivateTimeEditor(editTime, min, max, visualDoc.SelectedEvent.Event);
                        }
                        else
                            mtls.Enabled = false;
                    }
                }
            }
            //else if (e.MostTopSelectedElement == VisualDocElement.Story)
            //{
            //    //this.selectedStoryBases.Clear();
            //    //this.selectedStoryBases.Add(visualDoc.SelectedStory.Story);
            //   // OnStorySelected();

            //}
            //else if (e.MostTopSelectedElement == VisualDocElement.None)
            //{
            //    //OnExperimentSelected();
            //}

            toolStripButtonAddEvent.Enabled = visualDoc.SelectedStory != null;
            toolStripButtonSplit.Enabled = visualDoc.SelectedStory != null;
            toolStripButtonNewObservationPoint.Enabled = visualDoc.SelectedStory != null;


            Invalidate();

            OnObjectSelectionChanged(e);
        }



        void OnHighLightedElementChanged(object sender, EventArgs e)
        {
            Invalidate();
            if (visualDoc.CurrentlyHighLightedElement != null)
            {
                Debug.WriteLine("XemleViewer: something highlightes");
                toolTip1.Active = true;
                int x = visualDoc.CurrentlyHighLightedElement.Bounds.X + visualDoc.CurrentlyHighLightedElement.Bounds.Width + 2;
                int y = visualDoc.CurrentlyHighLightedElement.Bounds.Y;

                x += innerLeftMargin;
                y += innerTopMargin - 20;

                if (visualDoc.CurrentlyHighLightedElement is VisObserverPoint)
                {
                    VisObserverPoint vop = visualDoc.CurrentlyHighLightedElement as VisObserverPoint;
                    toolTip1.Show(vop.ObservationPoint.TimePoint.ToString(), this, x, y, 5000);

                }
                else if (visualDoc.CurrentlyHighLightedElement is VisEvent)
                {
                    VisEvent vop = visualDoc.CurrentlyHighLightedElement as VisEvent;
                    toolTip1.Show(vop.Event.Label + "\r\n" + vop.Event.TimePoint.ToString(), this, x, y, 5000);

                }
                else if (visualDoc.CurrentlyHighLightedElement is VisSwitchDot)
                {
                    VisSwitchDot vop = visualDoc.CurrentlyHighLightedElement as VisSwitchDot;
                    toolTip1.Show(vop.ChangedVariables, this, x, y, 5000);

                }
            }
            else
            {
                Debug.WriteLine("XemleViewer: nothing highlightes");
                toolTip1.Active = false;
            }
        }
        #endregion


        public event EventHandler<SelectedElementChangedEventArgs> ObjectSelectionChanged;

        protected virtual void OnObjectSelectionChanged(SelectedElementChangedEventArgs vde)
        {
            if (ObjectSelectionChanged != null)
                ObjectSelectionChanged(this, vde);
        }


    }

    enum TimeScrollMode
    {
        Week,
        Day,
        Hour,
        Minute,
        Second,
        Default
    }
}
